package org.reference.generic;


import java.util.ArrayList;
import java.util.List;

import org.reference.generic.Process.OnCompleteListenner;
import org.reference.generic.base.Item;
import org.reference.generic.base.Manager;
import org.reference.generic.base.Parameter;
import org.reference.generic.base.ReferenceParameter;
import org.reference.generic.information.Gene;
import org.reference.generic.work.Machine;
import org.reference.generic.work.Schedule;

import util.Log;

/**
 * 
 */
public class GeneManager extends Manager implements Gene.OnCompleteListenner  {

    /**
     * 
     */
    public GeneManager() {
    }

    /**
     * 
     */
    private Parameter generation;

    /**
     * 
     */
    private int processCompleteCount;

    /**
     * 
     */
    private OnCompleteListenner onProcessCompleteListenner;
    
    private OnCompleteListenner onCompleteListenner;
    /**
     * @param onCompleteListenner
     */
    public void setOnCompleteListenner(OnCompleteListenner onCompleteListenner) {
        this.onCompleteListenner = onCompleteListenner;
    }
    
    /**
     * @param result
     */
    public int execute() {
    	int result = 0;
    	
    	return result;
    }

    /**
     * 
     */
    public void printInputInformation() {
      }

    /**
     * 
     */
    public void printResultInformation() {
    	
    }
    
    List<Gene> genePopulation = new ArrayList<Gene>();
    
	@Override
	public void init(Parameter parameters, List<ReferenceParameter> rpList ) {
		
		int geneNumber = parameters.getValueToInt(Parameter.TYPE_GENE_POPULATION);
		
		for(int i=0; i<geneNumber;i++){
			Gene gene = new Gene(parameters);
			gene.setOnCompleteListenner(this);
			gene.setName("gene "+i);
			gene.makeProcess(parameters.getValueToInt(Parameter.TYPE_REFERENCE_SIZE), parameters, rpList );
			genePopulation.add(gene);
		}
	}
	
	@Override
	public void getResult() {
		
		Log.debug("====================-GENE CONSTRUCTION==========================");
		for (Gene genep : genePopulation) {
			System.out.println(genep.getName());
			System.out.println("루트노드 " + genep.getRootNode().getName());

			for (int j = 0; j < genep.getRootNode().getArity(); j++) {
				System.out.println("첫번째자식 " + genep.getRootNode().getChild(j).getName());
				for (int k = 0; k < genep.getRootNode().getChild(j).getArity(); k++) {
					System.out.println("두번째자식 "+ genep.getRootNode().getChild(j).getChild(k).getName());
//					for (int p = 0; p < genep.getRootNode().getChild(j).getChild(k).getArity(); p++) {
//						Log.debug("세번째자식 "+ genep.getRootNode().getChild(j).getChild(k).getChild(p).getName());
//					}
				}
			}
		}
		Log.debug(" ====================-GENE CONSTRUCTION END==========================");
		Log.debug("");
		Log.debug(" ====================-OPERATION START==========================");
		for (int i = 0; i < genePopulation.size(); i++) {
			Log.debug("----------------Gene " + i + " START-----------------------");
			for (int j = 0; j < genePopulation.get(i).processList.size(); j++) {
				Log.debug("----------------Process " + j+ " START-----------------------");
				for (int p = 0; p < genePopulation.get(i).processList.get(j).getSc().getMm().getMachineIndex().size(); p++) {
					Log.debug(genePopulation.get(i).getName()+" "+ genePopulation.get(i).processList.get(j).getName()+ " 머신 인덱스 "+genePopulation.get(i).processList.get(j).getSc().getMm().getMachineIndex().get(p).getIndex());
					for (int q = 0; q < genePopulation.get(i).processList.get(j).getSc().getMm().getMachineIndex().get(p).getMachineSchedule().size(); q++) {
						Log.debug("잡 인덱스 "+ genePopulation.get(i).processList.get(j).getSc().getMm().getMachineIndex().get(p).getMachineSchedule().get(q).getJobIndex() + " 잡 작업시간 " + genePopulation.get(i).processList.get(j).getSc().getMm().getMachineIndex().get(p).getMachineSchedule().get(q).getProcessingTime());
					}
				}
				Log.debug("----------------Process "+ j+ " END-----------------------");
			}
			Log.debug("----------------Gene " + i + " END-----------------------");
		}

		Log.debug("------------------SUMMARY---------------------");
		for (int k = 0; k < genePopulation.size(); k++) {
			for (int i = 0; i < genePopulation.get(k).processList.size(); i++) {
				Log.debug(genePopulation.get(k).getName() + " "+ genePopulation.get(k).processList.get(i).getName()+ " 피트니스 "+ genePopulation.get(k).processList.get(i).getFitness());
			}
		}

		for (int k = 0; k < genePopulation.size(); k++) {
			Log.debug(genePopulation.get(k).getName() + " " + " 에버리지 피트니스 "+ genePopulation.get(k).getAverageFiness());
		}

		Log.debug("베스트 진 " + getBestGene());
		Log.debug("=========================OPERATION END===========================");
	}
	
	public void run(){
		
		for (Gene geneRun : genePopulation) {
			geneRun.run();
		}
	}
	
	public String getBestGene(){
		
		double minAverageFitness = Double.MAX_VALUE;
		Gene temp = null;

		for (Gene geneC : genePopulation) {

			if (minAverageFitness > geneC.getAverageFiness()) {
				temp = geneC;
				minAverageFitness = geneC.getAverageFiness();
			}

		}
		
		return temp.getName();
	}

	 public interface OnCompleteListenner {
	        /**
	         * @param 
	         */
	        public abstract void onComplete(GeneManager geneManager);
	 }
	
	@Override
	public void onComplete(Gene gene) {

		
		if (onCompleteListenner != null) {

			onCompleteListenner.onComplete(this);
		}
	
		else {
			getResult();
		}	
	}
}
